﻿function BurnDownManager(canvas, globalOffset, labels, storyPoints) {
  // n.b.: ftp means 'for testing purpose'
  // n.b.: mtp means 'make this private'

  var context;
  if (canvas[0] && canvas[0].getContext) { context = canvas[0].getContext('2d'); }
  else { return; }

  // magic numbers
  var howManyYMarks = 10;
  var maxStoryPoints = getFullScale(storyPoints[0]);
  var storyPointsStep = maxStoryPoints / 9;

  // globals
  var maxX = canvas.width() - (2 * globalOffset); // f(canvas, globalOffset)
  var maxY = canvas.height() - (2 * globalOffset); // f(canvas, globalOffset)
  var stepX = Math.round(maxX / (labels.length - 1)); // todo: test this
  var stepY = Math.round(maxY / (howManyYMarks - 1));

  // style
  var font = 'Calibri';

  this.drawChart = function () {
    // the strategy
    this.drawGridLineX();
    this.drawGridLineY();
    this.drawAxis();
    this.drawIdeal();
    this.drawMarksX();
    this.drawLabelX();
    this.drawMarksY();
    this.drawLabelY();
    this.drawSegments();
    this.drawSegmentsLabels();
    return true; // ftp
  };

  this.drawGridLineX = function () { // mtp
    var pos = maxY + globalOffset;
    var deltaX = globalOffset;
    context.beginPath();
    context.strokeStyle = '#ccc';
    for (var i = 1; i < labels.length; i++) { // todo: labels.length - 1 (no right line)
      var x = i * stepX + deltaX;
      context.moveTo(x, pos);
      context.lineTo(x, globalOffset);
      context.stroke();
    }
    return true; // ftp
  };

  this.drawGridLineY = function () { // mtp
    var pos = globalOffset;
    var deltaY = globalOffset;
    context.beginPath();
    context.strokeStyle = '#ccc';
    for (var i = 0; i < howManyYMarks - 1; i++) { // todo: i = 1 (no top line)
      var y = i * stepY + deltaY;
      context.moveTo(pos, y);
      context.lineTo(maxX + globalOffset, y);
      context.stroke();
    }
    return true; // ftp
  };

  this.drawAxis = function () { // mtp
    context.beginPath();
    context.strokeStyle = '#000';
    context.moveTo(globalOffset, globalOffset);
    context.lineTo(globalOffset, maxY + globalOffset);
    context.lineTo(maxX + globalOffset, maxY + globalOffset);
    context.stroke();
    return true; // ftp
  };

  this.drawIdeal = function () {
    context.beginPath();
    context.lineWidth = 2;
    context.strokeStyle = '#c00';
    var scaledPoints = maxY * parseInt(storyPoints[0]) / maxStoryPoints; // argh!
    context.moveTo(globalOffset, maxY - scaledPoints + globalOffset);
    context.lineTo(maxX + globalOffset, maxY + globalOffset);
    context.stroke();
    return true;
  };

  this.drawMarksX = function () {
    var pos = maxY + globalOffset;
    var deltaX = globalOffset;
    var deltaY = 4;
    context.beginPath();
    context.strokeStyle = '#000';
    for (var i = 1; i < labels.length - 1; i++) {
      var x = i * stepX + deltaX;
      context.moveTo(x, pos - deltaY);
      context.lineTo(x, pos + deltaY);
      context.stroke();
    }
    return true;
  };

  this.drawLabelX = function () {
    var deltaX = globalOffset;
    var xOffset = 15;
    var yOffset = 25;
    context.font = 'normal 12px ' + font;
    for (var i = 0; i < labels.length; i++) {
      var x = i * stepX + deltaX;
      context.fillText(labels[i], x - xOffset, maxY + globalOffset + yOffset);
    }
    return true;
  };

  this.drawMarksY = function () {
    var pos = globalOffset;
    var deltaX = 4;
    var deltaY = globalOffset;
    context.beginPath();
    context.strokeStyle = '#000';
    for (var i = 1; i < howManyYMarks - 1; i++) {
      var y = i * stepY + deltaY;
      context.moveTo(pos - deltaX, y);
      context.lineTo(pos + deltaX, y);
      context.stroke();
    }
    return true;
  };

  this.drawLabelY = function () {
    var deltaY = globalOffset;
    var xOffset = 25;
    var yOffset = 5;
    context.font = 'normal 12px ' + font;
    for (var i = 0; i < howManyYMarks - 1; i++) {
      var y = i * stepY + deltaY;
      context.fillText(maxStoryPoints - storyPointsStep * i, globalOffset - xOffset, y + yOffset);
    }
    return true;
  };

  this.drawSegments = function () {
    for (var i = 0; i < storyPoints.length - 1; i++) {
      this.drawSegment({ fromIndex: i, toIndex: i + 1 });
    }
    return true;
  };

  this.drawSegment = function (points) { // mtp
    context.beginPath();
    context.lineWidth = 2;
    context.strokeStyle = '#0c0';
    context.moveTo(globalOffset + points.fromIndex * stepX, maxY - getScaledPoints(storyPoints[points.fromIndex]) + globalOffset);
    context.lineTo(globalOffset + points.toIndex * stepX, maxY - getScaledPoints(storyPoints[points.toIndex]) + globalOffset);
    context.stroke();
  };

  function getScaledPoints(points) {
    return maxY * parseInt(points) / maxStoryPoints;
  }

  this.drawSegmentsLabels = function () {
    for (var i = 0; i < storyPoints.length; i++) {
      this.drawSegmentLabel({ fromIndex: i });
    }
    return true;
  };

  this.drawSegmentLabel = function (point) {
    context.font = 'bold 12px ' + font;
    var labelOffset = 5;
    context.fillText('(' + storyPoints[point.fromIndex] + ')', (globalOffset + (point.fromIndex * stepX) + labelOffset), maxY - getScaledPoints(storyPoints[point.fromIndex]) + globalOffset - labelOffset);
    return true;
  };

  this.getFullScale = function (points) { // ftp
    return getFullScale(points);
  };
  
  function getFullScale(points) {
    var factor = 9;
    var div = Math.floor(points / factor);
    return (div + 1) * factor;
  }
}
